#ifndef _LITE_FRAME_PROTOCOL_H_
#define _LITE_FRAME_PROTOCOL_H_

#include <stdint.h>
#include <stdbool.h>

#ifndef RET_OK
#define RET_OK        0     /* ret ok */
#endif
#ifndef RET_ERR
#define RET_ERR     -1     /* ret err */
#endif

/**
 * protocol handler head
 * +----------------+----------------+----------------+----------------+----------------+----------------+
 * | sync code      | rolling counter| crc16          | mask           | count          | total length   |
 * +----------------+----------------+----------------+----------------+----------------+----------------+
 * | byte0          | byte1          | byte2-3        | byte4          | byte5          | byte6-7        |
 * +----------------+----------------+----------------+----------------+----------------+----------------+
 */
#define RING_BUF_HEADER_SIZE            (8)
#define RING_BUF_SYNC_CODE_OFFSET       (0)
#define RING_BUF_ROLLING_COUNTER_OFFSET (1)
#define RING_BUF_CRC_OFFSET             (2)
#define RING_BUF_FRAME_MASK_OFFSET      (4)
#define RING_BUF_FRAME_INDEX_OFFSET     (5)
#define RING_BUF_TOTAL_LENGTH_OFFSET    (6)
#define RING_BUF_DATA_OFFSET            (8)
#define RING_BUF_START_FRAME_SYNC       (0xAA)
#define RING_BUF_MIDDLE_FRAME_SYNC      (0x55)
#define RING_BUF_FRAGMENT_SIZE          (256)
#define RING_BUF_SWAP_SIZE              (RING_BUF_FRAGMENT_SIZE * 20)

#define TP_FRAG_FINISH_FLAG             (0x01)
#define TP_FRAG_NOT_FINISH_FLAG         (0x00)
#define TP_FRAGMENT_VALID_SIZE          (RING_BUF_FRAGMENT_SIZE-RING_BUF_HEADER_SIZE)

typedef struct {
    /* write statistic */
    /* link layer statistic */
    uint32_t set_start_frag_count;
    uint32_t set_middle_frag_count;
    uint32_t set_end_frag_count;
    double put_data_rate;        /**< put data rate */
    uint32_t put_data_error_count;
    uint32_t ring_buf_overflow;
    uint32_t set_sync_error_count;
    uint32_t set_rolling_error_count;
    uint32_t set_crc16_error_count;
    uint32_t set_total_frag_count;

    /* read statistic */
    uint32_t get_start_frag_count;
    uint32_t get_middle_frag_count;
    uint32_t get_end_frag_count;
    double get_data_rate;        /**< get data rate */
    uint32_t get_data_error_count;
    uint32_t get_sync_error_count;
    uint32_t get_rolling_error_count;
    uint32_t get_crc16_error_count;
    uint32_t get_total_frag_count;
    uint32_t get_first_frame_error;
} debug_statistic_t;

typedef struct {
    uint8_t rc;
    uint8_t *tmp_buf;             /**< tmp buffer */
    uint8_t *buf;                 /**< buffer */
    size_t size;                  /**< size */
    int32_t frag_cnt_set;         /**< fragment count set */
    int32_t frag_cnt_total;       /**< fragment count total */
    int32_t frag_last_copy;       /**< fragment last copy */
    int32_t frag_index;           /**< fragment index */
    int32_t frag_finish_flag;     /**< fragment finish flag */
} lite_frame_swap_t;

enum ring_buf_link_status {
    link_sync_start_frame = 7,     /**< sync code start in link layer*/
    link_sync_middle_frame,        /**< sync code error */
    link_sync_unknown_error,       /**< unknow sync code error */
    link_rolling_count_currect,    /**< rolling count currect */
    link_rolling_count_error,      /**< rolling count error */
    link_crc16_currect,            /**< crc currect */
    link_crc16_error               /**< crc16 error */
};

enum ring_buf_frame_status {
    start_frame = 0,              /**< start frame */
    end_frame,                    /**< end frame */
    single_frame,                 /**< single frame */
    middle_frame                  /**< middle frame */
};

typedef struct frame_header_mask {
    uint8_t start_bit : 1;        /**< start bit */
    uint8_t consec_bit:1;         /**< consecutive bit */
    uint8_t end_bit : 1;          /**< end bit */
    uint8_t reserve_bit:5;        /**< reserved bit */
} frame_header_mask_t;

typedef union {
    frame_header_mask_t element_value;  /**< frame header value */
    uint8_t byte_value;            /**< frame header byte value */
} frame_header_byte_t;

int32_t data_link_layer_check_interface(const uint8_t *buf, lite_frame_swap_t *swap);
int32_t transport_resolve_first_frame_interface(const uint8_t *buf, lite_frame_swap_t *swap);
int32_t transport_and_data_link_layer_set_interface(const uint8_t *usr_data, const size_t data_size, lite_frame_swap_t *swap);
int32_t transport_resolve_fragment_interface(const uint8_t *buf, lite_frame_swap_t *swap);
#endif /* _LITE_FRAME_PROTOCOL_H_ */